# -*- coding: utf-8 -*-

import os
import time

from app.Util.RedisClient import redis_client
from app.env import SURVEY_SERVER_ENV

TWEPOCH = 1541001600
DATACENTER_ID_BITS = 2
WORKER_ID_BITS = 1
SEQUENCE_ID_BITS = 3
MAX_DATACENTER_ID = 1 << DATACENTER_ID_BITS
MAX_WORKER_ID = 1 << WORKER_ID_BITS
MAX_SEQUENCE_ID = 1 << SEQUENCE_ID_BITS
MAX_TIMESTAMP = 1 << (32 - DATACENTER_ID_BITS - WORKER_ID_BITS - SEQUENCE_ID_BITS)
SEQUENCE_KEY = 'sequence:{}'


def make_snowflake(timestamp, datacenter_id, worker_id, sequence_id, twepoch=TWEPOCH):
    """generate a twitter-snowflake id, based on
    https://github.com/twitter/snowflake/blob/master/src/main/scala/com/twitter/service/snowflake/IdWorker.scala
    :param: timestamp_ms time since UNIX epoch in milliseconds"""

    sid = ((int(timestamp) - TWEPOCH) % MAX_TIMESTAMP) << DATACENTER_ID_BITS << WORKER_ID_BITS << SEQUENCE_ID_BITS
    sid += (datacenter_id % MAX_DATACENTER_ID) << WORKER_ID_BITS << SEQUENCE_ID_BITS
    sid += (worker_id % MAX_WORKER_ID) << SEQUENCE_ID_BITS
    sid += sequence_id % MAX_SEQUENCE_ID

    return sid


def next_topic_id(topic):
    key = SEQUENCE_KEY.format(topic)
    redis_client.incr(key)
    return redis_client.get(key)


def reset_topic_id(topic):
    return redis_client.getset(SEQUENCE_KEY.format(topic), 0)


def next_sequence(topic):
    timestamp = str(int(time.time()))
    sequence_mask = -1 ^ (-1 << SEQUENCE_ID_BITS)
    sequence_id = int(next_topic_id(topic)) & sequence_mask
    if sequence_id >= MAX_SEQUENCE_ID:
        reset_topic_id(topic)
    datacenter_id = SURVEY_SERVER_ENV
    sequence = make_snowflake(timestamp, datacenter_id, 1, sequence_id)
    return int(sequence)


def random_string(length):
    return os.urandom(length).hex()
